home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 19 / CU Amiga Magazine's Super CD-ROM 19 (1998)(EMAP Images)(GB)[!][issue 1998-02].iso / CUCD / Programming / LEDA / source / src / plane / _segment.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-16  |  4.9 KB  |  243 lines

  1. /*******************************************************************************
  2. +
  3. +  LEDA  3.1c
  4. +
  5. +
  6. +  _segment.c
  7. +
  8. +
  9. +  Copyright (c) 1994  by  Max-Planck-Institut fuer Informatik
  10. +  Im Stadtwald, 6600 Saarbruecken, FRG     
  11. +  All rights reserved.
  12. *******************************************************************************/
  13.  
  14.  
  15.  
  16. #include <LEDA/line.h>
  17. #include <math.h>
  18. #include <ctype.h>
  19.  
  20. static const double eps = 1e-10;
  21.  
  22.  
  23. //------------------------------------------------------------------------------
  24. // segments 
  25. //------------------------------------------------------------------------------
  26.  
  27. segment_rep::segment_rep()  { count = 1; }
  28.  
  29. segment_rep::segment_rep(const point& p, const point& q) 
  30. { start = p;
  31.   end   = q;
  32.   count = 1; 
  33.  
  34.   double dx = q.xcoord() - p.xcoord(); 
  35.   double dy = q.ycoord() - p.ycoord(); 
  36.  
  37.   if (dy==0)
  38.      slope = 0;
  39.   else
  40.      if (dx==0)
  41.        slope = MAXDOUBLE;
  42.      else
  43.        slope = dy/dx;
  44.  
  45.  
  46.   if (slope == MAXDOUBLE)
  47.      y_abs = -MAXDOUBLE;
  48.   else
  49.      y_abs =  p.ycoord() - slope * p.xcoord();
  50.  
  51.  
  52.   if (dx != 0 || dy != 0)
  53.       angle = atan2(dy,dx); 
  54.   else
  55.       angle = 0;
  56.  
  57. /*
  58.   angle = 0;
  59.   if (dx != 0 || dy != 0) 
  60.   { double cosfi=dx/sqrt(dx*dx+dy*dy);
  61.   
  62.     if (cosfi >=  1.0 ) 
  63.        angle = 0;
  64.     else
  65.       if (cosfi <= -1.0 ) 
  66.          angle = -M_PI;
  67.       else
  68.          angle = -acos(cosfi);
  69.  
  70.     if (dy > 0) angle = -angle;
  71.   }
  72. */
  73.     
  74. }
  75.   
  76.  
  77.  
  78. segment::segment() { PTR = new segment_rep; }
  79. segment::segment(const point& x, const point& y) { PTR = new segment_rep(x,y); }
  80. segment::segment(double x1, double y1, double x2, double y2) 
  81.                           { PTR = new segment_rep(point(x1,y1), point(x2,y2)); }
  82.  
  83. segment::segment(const point& p, double alpha, double length)
  84. { point q = p.translate(alpha,length);
  85.   PTR  = new segment_rep(p,q); 
  86.  }
  87.   
  88.  
  89. segment segment::translate(double alpha, double d) const
  90. { point p = ptr()->start.translate(alpha,d);
  91.   point q = ptr()->end.translate(alpha,d);
  92.   return segment(p,q);
  93.  }
  94.  
  95. segment segment::translate(const vector& v) const
  96. { point p = ptr()->start.translate(v);
  97.   point q = ptr()->end.translate(v);
  98.   return segment(p,q);
  99.  }
  100.  
  101.  
  102. ostream& operator<<(ostream& out, const segment& s) 
  103. { out << "[" << s.start() << "===" << s.end() << "]"; 
  104.   return out;
  105.  } 
  106.  
  107. /*
  108. istream& operator>>(istream& in, segment& s) 
  109. { double x1,x2,y1,y2; 
  110.   in >> x1 >> y1 >> x2 >> y2; 
  111.   s = segment(x1,y1,x2,y2); 
  112.   return in; 
  113.  } 
  114. */
  115.  
  116. istream& operator>>(istream& in, segment& s) 
  117. { // syntax: {[} p {===} q {]}
  118.  
  119.   point p,q; 
  120.   char c;
  121.  
  122.   do in.get(c); while (isspace(c));
  123.   if (c != '[') in.putback(c);
  124.  
  125.   in >> p;
  126.  
  127.   do in.get(c); while (isspace(c));
  128.   while (c== '=') in.get(c);
  129.   while (isspace(c)) in.get(c);
  130.   in.putback(c);
  131.  
  132.   in >> q; 
  133.  
  134.   do in.get(c); while (c == ' ');
  135.   if (c != ']') in.putback(c);
  136.  
  137.   s = segment(p,q); 
  138.   return in; 
  139.  
  140.  } 
  141.  
  142.  
  143.  
  144.  
  145. double segment::angle(const segment& s) const
  146. {
  147.   double cosfi,fi,norm;
  148.   
  149.   double dx  = ptr()->end.ptr()->x - ptr()->start.ptr()->x; 
  150.   double dy  = ptr()->end.ptr()->y - ptr()->start.ptr()->y; 
  151.  
  152.   double dxs = s.ptr()->end.ptr()->x - s.ptr()->start.ptr()->x; 
  153.   double dys = s.ptr()->end.ptr()->y - s.ptr()->start.ptr()->y; 
  154.   
  155.   cosfi=dx*dxs+dy*dys;
  156.   
  157.   norm=(dx*dx+dy*dy)*(dxs*dxs+dys*dys);
  158.  
  159.   if (norm == 0) return 0;
  160.  
  161.   cosfi /= sqrt( norm );
  162.  
  163.   if (cosfi >=  1.0 ) return 0;
  164.   if (cosfi <= -1.0 ) return M_PI;
  165.   
  166.   fi=acos(cosfi);
  167.  
  168.   if (dx*dys-dy*dxs>0) return fi;
  169.  
  170.   return -fi;
  171.  
  172. }
  173.  
  174.  
  175. double segment::distance(const segment& s) const
  176. { if (angle(s)!=0) return 0;
  177.   return distance(s.ptr()->start);
  178.  }
  179.  
  180. double  segment::distance() const
  181. { return distance(point(0,0)); }
  182.  
  183. double segment::distance(const point& p) const
  184. { segment s(ptr()->start,p);
  185.   double l = s.length();
  186.   if (l==0) return 0;
  187.   else return l*sin(angle(s));
  188.  }
  189.  
  190.  
  191. double  segment::y_proj(double x)  const
  192. { return  ptr()->start.ptr()->y - ptr()->slope * (ptr()->start.ptr()->x - x); }
  193.  
  194. double  segment::x_proj(double y)  const
  195. { if (vertical())  return  ptr()->start.ptr()->x;
  196.   return  ptr()->start.ptr()->x - (ptr()->start.ptr()->y - y)/ptr()->slope; }
  197.  
  198.  
  199.  
  200. bool segment::intersection(const segment& s, point& inter) const
  201. { double cx,cy;
  202.  
  203.   if (slope() == s.slope()) return false;
  204.  
  205.   if (vertical())
  206.      cx = xcoord1();
  207.   else
  208.      if (s.vertical())
  209.         cx = s.xcoord1();
  210.      else
  211.         cx = (s.y_abs()-y_abs())/(slope()-s.slope());
  212.  
  213.   if(xcoord1() < cx &&  xcoord2()  < cx ||  xcoord1() > cx  && xcoord2() > cx ||
  214.    s.xcoord1() < cx && s.xcoord2() < cx || s.xcoord1() > cx && s.xcoord2() > cx)
  215.   return false;
  216.  
  217.   if (vertical())
  218.      cy = s.slope() * cx + s.y_abs();
  219.   else
  220.      cy = slope() * cx + y_abs();
  221.  
  222.   inter = point(cx,cy);
  223.  
  224.   return true;
  225. }
  226.  
  227.  
  228. segment segment::rotate(double alpha) const
  229. {  double  l = length();
  230.    point p = start();
  231.    double beta = alpha + angle();
  232.    return segment(p,beta,l);
  233. }
  234.  
  235. segment segment::rotate(const point& origin, double alpha) const
  236. {  point p = start().rotate(origin,alpha);
  237.    point q = end().rotate(origin,alpha);
  238.    return segment(p,q);
  239. }
  240.  
  241.  
  242.